package com.cloudkinto.service.user.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.DicBusinessConstant;
import com.cloudkinto.common.DicBusinessItemConstant;
import com.cloudkinto.common.common.MD5Util;
import com.cloudkinto.common.common.PersonalInfoUtils;
import com.cloudkinto.common.common.VerificationCodeUtil;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.AmazonUtil;
import com.cloudkinto.common.utils.HmacUtil;
import com.cloudkinto.common.utils.OkHttpUtils;
import com.cloudkinto.common.utils.OrderCodeUtil;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.service.email.MailSenderService;
import com.cloudkinto.service.file.FileService;
import com.cloudkinto.service.role.RoleService;
import com.cloudkinto.service.user.UserService;
import com.cloudkinto.service.user.captchamode.CaptchaModeService;
import com.cloudkinto.service.user.captchamode.Context;
import com.cloudkinto.service.user.captchamode.impl.MailSendMsgImpl;
import com.cloudkinto.service.user.captchamode.impl.PhoneSendMsgImpl;
import com.cloudkinto.service.user.vo.*;
import com.cloudkinto.session.UserSession;
import com.cloudkinto.session.UserSessionException;
import com.cloudkinto.session.UserSessionManager;
import okhttp3.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.SocketException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author 张永远
 * @since 2020-05-27
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class UserServiceImpl extends ServiceImpl<UserDao, UserDo> implements UserService {
    private static final String AUTHORIZESTATEKEY = "oms_authorize_key";
    @Value("${gbc.login.verificationCode}")
    private boolean verificationCode;

    @Autowired
    private UserDao dao;
    @Autowired
    private FileService fileService;
    @Autowired
    private CompanyDao companyDao;
    @Autowired
    private FileDao fileDao;
    @Autowired
    private RoleDao roleDao;
    @Autowired
    private RoleService roleService;
    @Autowired
    private ShopDao shopDao;
    @Autowired
    private DicBusinessItemDao dicBusinessItemDao;
    @Autowired
    private UserSessionManager userSessionManager;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MailSenderService mailSenderService;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    private String AMZACCESSTOKEN = "AMZACCESSTOKEN:";
    private String STSSESSIONTOKEN = "STSSESSIONSTOKEN";

    @Override
    public UserLoginSuccessRes login(UserLoginReq req) {
        //校验验证码
        if (verificationCode) {
            String verificationCode = (String) redisTemplate.opsForValue().get("verificationCode:" + req.getKey());
            if (StringUtils.isBlank(verificationCode)) {
                throw new BizException("验证码已过期");
            } else if (!(verificationCode.equals(req.getVerificationCode()))) {
                throw new BizException("验证码错误");
            }
        }


        MD5Util md5 = new MD5Util(SysConstant.SALT_STRING, "MD5");

        LambdaQueryWrapper<UserDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDo::getUserAccount, req.getUserAccount())
                .eq(UserDo::getUserPassword, md5.encode(req.getUserPassword()))
                .eq(UserDo::getUserType, 1);
        UserDo userDo = this.baseMapper.selectOne(wrapper);
        if (userDo == null) {
            throw new BizException("账号密码错误");
        } else if (userDo.getUserStatus() != 1) {
            throw new BizException("账号正在审核中..");
        }

        //创建会话
        UserSession session = userSessionManager.createSession(userDo);

        UserLoginSuccessRes res = new UserLoginSuccessRes();
        res.setUserId(session.getUserId());
        res.setSessionId(session.getSessionId());
        res.setUserAccount(userDo.getUserAccount());
        res.setUserName(userDo.getUserName());
        res.setHeadUrl(fileService.getFilePath(userDo.getHeadFileId()));
        res.setMenuTree(roleService.getMenuTree(userDo.getRoleId(), req.getLanguage()));

        return res;
    }

    @Override
    public UserLoginSuccessRes main(String token) {
        UserSession session = userSessionManager.getSession(token);
        if (session == null) throw new UserSessionException();
        UserLoginSuccessRes res = new UserLoginSuccessRes();
        UserDo userDo = dao.selectById(session.getUserId());
        if (userDo == null) throw new BizException("账号不存在");
        res.setUserId(session.getUserId());
        res.setSessionId(session.getSessionId());
        res.setUserAccount(userDo.getUserAccount());
        res.setUserName(userDo.getUserName());
        res.setHeadUrl(fileService.getFilePath(userDo.getHeadFileId()));
        res.setMenuTree(roleService.getMenuTree(userDo.getRoleId(), 1));
        return res;
    }

    @Override
    public SingleResult getToken(String username, String password) {
//        MD5Util md5 = new MD5Util(SysConstant.SALT_STRING, "MD5");

        LambdaQueryWrapper<UserDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDo::getUserAccount, username)
                .eq(UserDo::getUserPassword, password)
                .eq(UserDo::getUserType, 1);
        UserDo userDo = this.baseMapper.selectOne(wrapper);
        if (userDo == null) {
            throw new BizException("账号密码错误");
        } else if (userDo.getUserStatus() != 1) {
            throw new BizException("账号正在审核中..");
        }

        //创建会话
        UserSession session = userSessionManager.createSession(userDo);
        return SingleResult.success(session.getSessionId());
    }

    @Override
    public void logout(String token) {
        userSessionManager.clearSession(token);
    }

    @Override
    public UserRegisterReq register(UserRegisterReq req) {
        checkRegister(req);

        if (req.getCompanyFileId() != null) {
            fileService.uploadFile(req.getCompanyFileId());
        }

        CompanyDo companyDo = new CompanyDo();
        companyDo.setName(req.getCompanyName());
        companyDo.setFileId(req.getCompanyFileId());
        companyDo.setCreateTime(new Date());
        companyDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        companyDao.insert(companyDo);
        companyDo.setCompanyCode(OrderCodeUtil.generateCompanyCode(companyDo.getId()));
        companyDao.updateById(companyDo);

        MD5Util md5 = new MD5Util(SysConstant.SALT_STRING, "MD5");

        LambdaQueryWrapper<RoleDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleDo::getDevCode, SysConstant.clientAdmin);
        RoleDo roleDo = roleDao.selectOne(wrapper);

        UserDo userDo = new UserDo();
        //注册用户默认指定 客户管理员角色
        if (roleDo != null) {
            userDo.setRoleId(roleDo.getId());
        }
        userDo.setUserPassword(md5.encode(req.getUserPassword()));
        userDo.setUserAccount(req.getUserAccount());
        userDo.setUserName(req.getUserName());
        userDo.setUserMail(req.getUserMail());
        userDo.setUserPhone(req.getUserPhone());
        userDo.setCompanyId(companyDo.getId());
        userDo.setUserStatus(0);
        userDo.setUserType(1);
        userDo.setCreateTime(new Date());
        userDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        dao.insert(userDo);
        threadPoolTaskExecutor.execute(() -> {
            mailSenderService.sendEmail("有新的客户注册", "名字：" + req.getUserName() + "<br />公司名称：" + req.getCompanyName() +
                    "<br />联系电话：" + req.getUserPhone() +
                    "<br />电子邮箱：" + req.getUserMail() + "<br />公司证件：" + fileService.getFilePath(req.getCompanyFileId()), SysConstant.cloudkintEmail);
        });
        return req;
    }

    private void checkRegister(UserRegisterReq req) {
        LambdaQueryWrapper<UserDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDo::getUserAccount, req.getUserAccount());
        int count = this.baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BizException("该账号已经存在");
        }
    }


    @Override
    public SingleResult bindKeyInit() {

        List<Map> platformList = new ArrayList<>();

        LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.platform);

        List<DicBusinessItemDo> itemDoList = dicBusinessItemDao.selectList(wrapper);
        List<DicBusinessItemDo> collect = itemDoList.stream().filter(dicBusinessItemDo -> dicBusinessItemDo.getDicBusinessId() != DicBusinessItemConstant.other).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            for (DicBusinessItemDo itemDo : collect) {
                Map map = new HashMap();
                map.put("platformId", itemDo.getId());
                map.put("value", itemDo.getDicItemValue());
                platformList.add(map);
            }
        }

        return SingleResult.success(platformList);
    }

    @Override
    public SingleResult keySecret(Long plantFormId, Long shopId) {
        Map map = new HashMap();
        ShopDo shopDo = shopDao.selectById(shopId);
        if (shopDo != null) {
            if (plantFormId.equals(DicBusinessItemConstant.amazon)) {
                map.put("key", shopDo.getAmazonSellerId());
                map.put("value", shopDo.getAmazonToken());
                map.put("keyName", "卖家账号");
                map.put("valueName", "访问token");
            } else if (plantFormId.equals(DicBusinessItemConstant.rakuton)) {
                map.put("key", shopDo.getRakutenLicense());
                map.put("value", shopDo.getRakutenSecret());
                map.put("keyName", "licenseKey");
                map.put("valueName", "服务秘钥（serviceSecret）");
            } else if (plantFormId.equals(DicBusinessItemConstant.qooTen)) {
                map.put("key", shopDo.getQootenKey());
                map.put("value", shopDo.getQootenPwd());
                map.put("id", shopDo.getQootenId());
                map.put("keyName", "秘钥");
                map.put("valueName", "密码");
                map.put("idName", "账号");
            }
        }
        return SingleResult.success(map);
    }

    @Override
    public SingleResult shopListFromPlantForm(Long plantFormId, Long companyId) {

        List<Map> shopList = new ArrayList<>();
        LambdaQueryWrapper<ShopDo> shopDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        shopDoLambdaQueryWrapper
//                .eq(ShopDo::getPlatformId, plantFormId)
                .eq(ShopDo::getCompanyId, companyId);
        List<ShopDo> shopDoList = shopDao.selectList(shopDoLambdaQueryWrapper);
        if (!CollectionUtils.isEmpty(shopDoList)) {
            for (ShopDo shopDo : shopDoList) {
                Map itemMap = new HashMap();
                itemMap.put("shopId", shopDo.getId());
                itemMap.put("value", shopDo.getShopName());
                shopList.add(itemMap);
            }
        }
        if (DicBusinessItemConstant.Shopify.intValue() == plantFormId.intValue()) {
            Map itemMap = new HashMap();
            itemMap.put("shopId", null);
            itemMap.put("value", "作为新店铺添加");
            shopList.add(itemMap);
        }
        return SingleResult.success(shopList);
    }

    @Override
    public SingleResult addInit(Long companyId) {
        Map result = new HashMap();

        List<Map> roleList = new ArrayList<>();

        LambdaQueryWrapper<RoleDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleDo::getRoleType, 1);
        List<RoleDo> roleDoList = roleDao.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(roleDoList)) {
            for (RoleDo roleDo : roleDoList) {
                Map map = new HashMap();
                map.put("id", roleDo.getId());
                map.put("value", roleDo.getRoleName());
                map.put("code", roleDo.getDevCode());
                roleList.add(map);
            }
        }
        result.put("roleList", roleList);

        List<Map> shopList = new ArrayList<>();
        LambdaQueryWrapper<ShopDo> shopDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        shopDoLambdaQueryWrapper.eq(ShopDo::getCompanyId, companyId);
        List<ShopDo> shopDoList = shopDao.selectList(shopDoLambdaQueryWrapper);
        if (CollectionUtils.isNotEmpty(shopDoList)) {
            for (ShopDo shopDo : shopDoList) {
                Map map = new HashMap();
                map.put("id", shopDo.getId());
                map.put("value", shopDo.getShopName());
                shopList.add(map);
            }
        }
        result.put("shopList", shopList);
        return SingleResult.success(result);
    }

    @Override
    public UserBuildReq add(UserBuildReq req, Long userId, Long companyId) {
        addCheck(req);

        MD5Util md5 = new MD5Util(SysConstant.SALT_STRING, "MD5");

        UserDo entityDo = new UserDo();
        BeanUtils.copyProperties(req, entityDo);
        handlerAddBefore(entityDo, userId);

        entityDo.setUserPassword(md5.encode(req.getUserPassword()));
        entityDo.setUserStatus(1);
        entityDo.setUserType(1);
        entityDo.setShopId(req.getShopId());
        entityDo.setCompanyId(companyId);
        dao.insert(entityDo);
        return req;
    }

    //新增校验
    private void addCheck(UserBuildReq req) {
        LambdaQueryWrapper<UserDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDo::getUserAccount, req.getUserAccount());
        int count = this.baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BizException("该账号已经存在,请重新输入");
        }
    }

    //做新增之前要执行的业务定制处理
    private void handlerAddBefore(UserDo entityDo, Long userId) {
        entityDo.setCreateBy(userId);
        entityDo.setCreateTime(new Date());
        entityDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
    }


    @Override
    public SingleResult updateInit(Long id) {
        UserDo entityDo = dao.selectById(id);
        if (entityDo == null) {
            throw new BizException("查无信息！");
        }
        UserDetailRes res = new UserDetailRes();

        res.setId(entityDo.getId());
        res.setUserAccount(entityDo.getUserAccount());
        res.setUserName(entityDo.getUserName());
        res.setUserMail(entityDo.getUserMail());
        res.setUserPhone(entityDo.getUserPhone());

        CompanyDo companyDo = companyDao.selectById(entityDo.getCompanyId());
        if (companyDo != null) {
            res.setCompanyName(companyDo.getName());
        }
        FileDo fileDo = fileDao.selectById(entityDo.getHeadFileId());
        if (fileDo != null) {
            res.setHeadFileUrl(fileService.getFilePath(fileDo.getId()));
            res.setHeadFileId(fileDo.getId());
            res.setFileName(fileDo.getFileName());
        }

        return SingleResult.success(res);
    }

    @Override
    public UserUpdateReq update(UserUpdateReq req, Long userId) {
        UserDo entityDo = dao.selectById(req.getId());

        if (req.getHeadFileId() != null) {
            fileService.deleteFile(entityDo.getHeadFileId());
            fileService.uploadFile2(req.getHeadFileId(), entityDo.getHeadFileId());
        }
        entityDo.setUserPhone(req.getUserPhone());
        entityDo.setUserMail(req.getUserMail());
        entityDo.setRoleId(req.getRoleId());
        entityDo.setShopId(req.getShopId());
        entityDo.setUserName(req.getUserName());
        entityDo.setHeadFileId(req.getHeadFileId());
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return req;
    }

    @Override
    public UpdatePasswordReq updatePassword(UpdatePasswordReq req, Long userId) {
        if (!req.getNewPassword().equals(req.getNewPasswordAgain())) {
            throw new BizException("两次输入密码不一致");
        }
        UserDo entityDo = dao.selectById(userId);
        MD5Util md5 = new MD5Util(SysConstant.SALT_STRING, "MD5");
        if (!(md5.encode(req.getPassword()).equals(entityDo.getUserPassword()))) {
            throw new BizException("原密码错误");
        }

        entityDo.setUserPassword(md5.encode(req.getNewPassword()));
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return req;
    }

    @Override
    public SingleResult bindKey(UserBindReq req, Long userId) {
        LambdaQueryWrapper<ShopDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShopDo::getId, req.getShopId());
        ShopDo shopDo = shopDao.selectOne(wrapper);
        if (shopDo == null) {
            throw new BizException("绑定失败，该平台下没有此店铺");
        }
        if (req.getPlatformId().equals(DicBusinessItemConstant.amazon)) {
//            shopDo.setAmazonSellerId(req.getKey());
//            shopDo.setAmazonToken(req.getValue());
            return SingleResult.success("请求成功", authorizeNow(req, 16L, userId));
        } else if (req.getPlatformId().equals(DicBusinessItemConstant.rakuton)) {
            shopDo.setRakutenLicense(req.getKey());
            shopDo.setRakutenSecret(req.getValue());
        } else if (req.getPlatformId().equals(DicBusinessItemConstant.qooTen)) {
            shopDo.setQootenId(req.getId());
            shopDo.setQootenKey(req.getKey());
            shopDo.setQootenPwd(req.getValue());
        }
        shopDo.setUpdateBy(userId);
        shopDo.setUpdateTime(new Date());
        shopDao.updateById(shopDo);
        return SingleResult.success("绑定成功", req);
    }

    private String authorizeComplete(String amazon_callback_uri, String amazon_state, String selling_partner_id) {
        return amazon_callback_uri + "?" + "";
    }

    //编辑校验
    private void updateCheck(Object req) {

    }

    /**
     * 返回给前端跳转亚马逊的url（授权页面）
     */
//    @Override
    public String authorizeNow(UserBindReq req, Long marketPlaceId, Long userId) {

        String state = UUID.randomUUID().toString();
        //放入缓存
        redisTemplate.opsForValue().set(AUTHORIZESTATEKEY + userId, state, 3000, TimeUnit.SECONDS);
        redisTemplate.opsForValue().set(state, req.getShopId(), 3000, TimeUnit.SECONDS);
        Map paramMap = new HashMap();
        paramMap.put("state", state);
        paramMap.put("application_id", GlobalConstants.amazonSecret);
        String url = "";
        if (StringUtils.isNotBlank(req.getAmazon_callback_uri())
                && StringUtils.isNotBlank(req.getAmazon_state())
                && StringUtils.isNotBlank(req.getSelling_partner_id())) {
            url = req.getAmazon_callback_uri() + "?amazon_state=" + URLEncoder.encode(req.getAmazon_state()) + "&state=" + state + "&redirect_uri=" + GlobalConstants.AmazonSPRedirectURL;
        } else {
            url = GlobalConstants.AmazonSPURL + "apps/authorize/consent?" + "application_id=" +  GlobalConstants.amazonAppId  + "&state=" + state + "&redirect_uri=" + GlobalConstants.AmazonSPRedirectURL;
        }
//        url += "&version=beta";
        return url;
    }

    @Override
    public SingleResult getAuthorizeMsg(Long shopId, Map<String, String> map, Long userId) {
        //验证state值
//        Object state = redisTemplate.opsForValue().get(AUTHORIZESTATEKEY + userId);
//        if (state == null || map.get("state") == null || !state.toString().equals(map.get("state"))) {
//            throw new BizException("授权超时,请重试");
//        }
        if (null == shopId) {
            Object value = redisTemplate.opsForValue().get(map.get("state"));
            if (value == null) {
                throw new BizException("未找到店铺");
            }
            shopId = Long.parseLong(value.toString());
        }
        String sellingPartnerId = map.get("selling_partner_id");
        String mws_auth_token = map.get("mws_auth_token");

        //判断 sellingPartnerId 唯一性 todo


        //您的应用程序用 LWA 授权码交换 LWA 刷新令牌
        Map paramMap = new HashMap();
        paramMap.put("grant_type", "authorization_code");
        paramMap.put("code", map.get("spapi_oauth_code"));
        paramMap.put("client_id", GlobalConstants.AmzSpClientId);
        paramMap.put("client_secret", GlobalConstants.AmzSpClientSecret);
        paramMap.put("redirect_uri", GlobalConstants.AmazonSPRedirectURL);

        ShopDo shopDo = shopDao.selectById(shopId);
        if (shopDo == null) {
            throw new BizException("该店铺不存在");
        }
        String body = null;
        try {
            body = AmazonUtil.spAPidoPOST("https://api.amazon.com/auth/o2/token", "", "", paramMap, JSON.toJSONString(paramMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (body == null) {
            throw new BizException("授权失败，请重试");
        }
        JSONObject jsonObject = JSONObject.parseObject(body);
        System.out.println("huajiyu打印的：" + body);
        if (jsonObject == null || jsonObject.getString("refresh_token") == null) {
            throw new BizException("授权失败，请重试");
        }

        shopDo.setAmazonSellerId(sellingPartnerId);
        shopDo.setAmazonToken(mws_auth_token);
        shopDo.setAmzSpLwa(jsonObject.getString("refresh_token"));
//        shopDo.setShopAuthorizeState(1L);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.YEAR, 1);
//        shopDo.setExpirationTime(calendar.getTime());
        shopDao.updateById(shopDo);

        redisTemplate.opsForValue().set(AMZACCESSTOKEN + shopDo.getId(), jsonObject.getString("access_token"), 3000, TimeUnit.SECONDS);
        return SingleResult.success();
    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(UserDo entityDo, Long userId) {
        entityDo.setUpdateBy(userId);
        entityDo.setUpdateTime(new Date());
    }


    @Override
    public int delete(Long id, Long userId) {
        UserDo entityDo = dao.selectById(id);
        handlerDeleteBefore(entityDo, userId);
        dao.updateById(entityDo);
        dao.updateById(entityDo);
        return dao.deleteById(id);
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(UserDo entityDo, Long userId) {
        entityDo.setDeleteBy(userId);
        entityDo.setDeleteTime(new Date());
    }

    @Override
    public SingleResult verificationCode() {
        Map map = VerificationCodeUtil.generateCode();
        String key = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("verificationCode:" + key, map.get("result"), 5 * 60, TimeUnit.SECONDS);
        map.remove("result");
        map.put("key", key);
        return SingleResult.success(map);
    }

    @Override
    public SingleResult getPhoneByAccount(String userAccount) {
        LambdaQueryWrapper<UserDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDo::getUserAccount, userAccount)
                .eq(UserDo::getUserType, 1);
        UserDo userDo = dao.selectOne(wrapper);
        if (userDo == null) throw new BizException("查无此账号");

        Map map = new HashMap();
        if (StringUtils.isNotBlank(userDo.getUserPhone())) {
            map.put("phone", PersonalInfoUtils.alipayAccountNo(userDo.getUserPhone(), 2));
        } else {
            map.put("phone", "该账号未绑定手机号，无法进行短信验证");
        }

        if (StringUtils.isNotBlank(userDo.getUserMail())) {
            map.put("mail", PersonalInfoUtils.alipayAccountNo(userDo.getUserMail(), 2));
        } else {
            map.put("mail", "该账号未绑定邮箱，无法进行邮箱验证");
        }

        map.put("userAccount", userDo.getUserAccount());

        return SingleResult.success(map);
    }


    @Override
    public SingleResult verificationCodeByPhone(SendMsgReq req) {
        LambdaQueryWrapper<UserDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDo::getUserAccount, req.getUserAccount()).eq(UserDo::getUserType, 1);
        UserDo userDo = dao.selectOne(wrapper);
        if (userDo == null) {
            throw new BizException("查无此账号");
        }
        if (req.getType() == 1) {//短信验证
            CaptchaModeService captchaModeService = new PhoneSendMsgImpl(userDo, redisTemplate);
            Context context = new Context(captchaModeService);
            context.contextSend(SysConstant.DELETE_FLAG_TRUE);
        } else if (req.getType() == 2) {//邮箱验证
            CaptchaModeService captchaModeService = new MailSendMsgImpl(userDo, redisTemplate, mailSenderService);
            Context context = new Context(captchaModeService);
            context.contextSend(SysConstant.DELETE_FLAG_TRUE);
        }
        return SingleResult.success("验证码发送成功，请及时查收", null);
    }

    @Override
    public SingleResult verificationCodeCheck(CheckCodeReq req) {
        //校验验证码
        String code = (String) redisTemplate.opsForValue().get("phoneCode:" + req.getUserAccount());
        if (StringUtils.isBlank(code) || !(code.equals(req.getCode()))) {
            throw new BizException("验证码错误，校验失败！");
        }

        //生成临时凭证 存入redis
        String key = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("phoneCodeKey:" + req.getUserAccount(), key, 30, TimeUnit.MINUTES);
        return SingleResult.success(key);
    }


    @Override
    public SingleResult findBackPassword(FindBackPasswordReq req) {
        String key = (String) redisTemplate.opsForValue().get("phoneCodeKey:" + req.getUserAccount());
        if (StringUtils.isBlank(key) || !(key.equals(req.getKey()))) {
            throw new BizException("会话过期请重新操作修改密码流程");
        }

        LambdaQueryWrapper<UserDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDo::getUserAccount, req.getUserAccount())
                .eq(UserDo::getUserType, 1);
        UserDo userDo = dao.selectOne(wrapper);
        if (userDo == null) throw new BizException("查无此账号,请检查账号是否正确");


        MD5Util md5 = new MD5Util(SysConstant.SALT_STRING, "MD5");
        userDo.setUserPassword(md5.encode(req.getNewPassword()));
        dao.updateById(userDo);

        return SingleResult.success("密码修改成功!", null);
    }

    //查询明细之后要执行的业务定制处理
    private Object handlerDetailAfter(Object res) {
        return res;
    }

    @Override
    public SingleResult pageInit() {
        return SingleResult.success("");
    }

    @Override
    public List<UserListPageRes> getList(Map<String, String> map) {
        QueryWrapper<UserDo> wrapper = queryBuild(map);
        List<UserDo> list = this.list(wrapper);
        List<UserListPageRes> result = handlerListAfter(list);
        return result;
    }

    @Override
    public PageResult getListPage(Map<String, String> map) {
        QueryWrapper<UserDo> wrapper = queryBuild(map);
        IPage<UserDo> page = pageInit(map);
        page = this.page(page, wrapper);
        List<UserListPageRes> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<UserListPageRes> handlerListAfter(List<UserDo> list) {
        List<UserListPageRes> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (UserDo userDo : list) {
                UserListPageRes res = new UserListPageRes();
                res.setUserAccount(userDo.getUserAccount());
                res.setUserName(userDo.getUserName());
                res.setId(userDo.getId());
                res.setUserMail(userDo.getUserMail());
                res.setUserPhone(userDo.getUserPhone());
                RoleDo roleDo = roleDao.selectById(userDo.getRoleId());
                if (roleDo != null) {
                    res.setRoleName(roleDo.getRoleName());
                }
                result.add(res);
            }
        }
        return result;
    }


    private IPage<UserDo> pageInit(Map<String, String> map) {
        IPage<UserDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<UserDo> queryBuild(Map<String, String> map) {
        QueryWrapper<UserDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.eq("company_id", Long.parseLong(map.get("companyId")))
                    .and(i -> i.like("user_account", map.get("keyword"))
                            .or().like("user_name", map.get("keyword"))
                            .or().like("user_phone", map.get("keyword")));
        } else {
            wrapper.eq("company_id", Long.parseLong(map.get("companyId")));
        }
        return wrapper;
    }

    @Override
    public SingleResult shopifyGetAuthorization(Long shopId, Long companyId, String code, String session, String state, String host, String hmac, String shop, String timestamp) {
        ShopDo shopDo = shopDao.selectById(shopId);
        if (shopDo == null & state != null) {
            shopDo = new ShopDo();
            shopDo.setShopName(shop.split("\\.")[0]);
            shopDo.setPlatformId(DicBusinessItemConstant.Shopify);
            shopDo.setCompanyId(companyId);
            shopDo.setCreateTime(new Date());
            shopDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
            shopDao.insert(shopDo);
            shopId = shopDo.getId();
        }
        StringBuilder data = new StringBuilder();
        if (StringUtils.isNotBlank(code)) {
            data.append("code=" + code);
        }
        if (StringUtils.isNotBlank(host)) {
            data.append("&");
            data.append("host=" + host);
        }
        if (StringUtils.isNotBlank(session)) {
            data.append("&");
            data.append("session=" + session);
        }
        if (StringUtils.isNotBlank(shop)) {
            data.append("&");
            data.append("shop=" + shop);
        }
        if (StringUtils.isNotBlank(state)) {
            data.append("&");
            data.append("state=" + state);
        }
        if (StringUtils.isNotBlank(timestamp)) {
            data.append("&");
            data.append("timestamp=" + timestamp);
        }
        if (data.toString().startsWith("&")) {
            data.replace(0, 1, "");
        }
//        if (true) return SingleResult.failure("504", "授权失败,请重试");
        String url;
        try {
            if (StringUtils.isBlank(code)) {
                if (!HmacUtil.HMACSHA256(data.toString(), GlobalConstants.ShopifySecret).equals(hmac))
                    return SingleResult.failure("鉴权失败");
                url = "https://" + shop + "/admin/oauth/authorize?" +
                        "client_id=" + GlobalConstants.ShopifyKey +
//                        "&scope=write_orders,read_locations,read_customers,read_fulfillments,write_fulfillments" +
                        "&scope=read_orders,write_orders,read_locations" +
                        "&redirect_uri=" + "https://www.cloudkinto.com/kinto/KeyBinding" +
                        "&state=" + System.currentTimeMillis() +
                        "&grant_options[]=value";
                System.out.println(url);
                return SingleResult.success(url);
            } else {
//                shopDo = shopDao.selectById(state.split("\\-")[1]);
//                if (shopDo == null) shopDo = shopDao.selectById(33);
                if (!HmacUtil.HMACSHA256(data.toString(), GlobalConstants.ShopifySecret).equals(hmac))
                    return SingleResult.failure("鉴权失败");
                url = "https://" + shop + "/admin/oauth/access_token";
                OkHttpClient.Builder client = OkHttpUtils.getUnsafeOkHttpClient().newBuilder();
                client.connectTimeout(60, TimeUnit.SECONDS)
                        .readTimeout(60, TimeUnit.SECONDS)
                        .writeTimeout(60, TimeUnit.SECONDS)
                        .retryOnConnectionFailure(true);
                System.out.println(url);
                Map<String, String> params = new HashMap<>();
                params.put("client_id", GlobalConstants.ShopifyKey);
                params.put("client_secret", GlobalConstants.ShopifySecret);
                params.put("code", code);
                Request request = new Request.Builder()
                        .addHeader("Content-Type", "application/json;charset=utf-8")
                        .post(RequestBody.create(MediaType.get("application/json"), JSON.toJSONString(params)))
                        .url(url)
                        .build();
                Response response = null;
                String body = "";
                try {
                    response = client.build().newCall(request).execute();
                    body = response.body().string();
                    System.out.println(body);
                    //{
                    //    "access_token": "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",
                    //    "scope": "write_orders,read_customers"
                    //}
                    JSONObject jsonObject = JSON.parseObject(body);
                    ShopDo shopUpdate = shopDao.selectById(shopId);
                    shopUpdate.setShopifyToken(jsonObject.getString("access_token"));
                    shopUpdate.setShopifyHost(shop);
                    shopDao.updateById(shopUpdate);
                } catch (SocketException e) {
                    e.printStackTrace();
                    return SingleResult.failure("504", "授权失败,请重试");
                } catch (IOException e) {
                    e.printStackTrace();
                    return SingleResult.failure("授权失败" + e.getMessage());
                }
                return SingleResult.success();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SingleResult.failure("授权失败");
    }


}

